<?php
/***
 * ActionLeaf (www.actionleaf.com / actionleaf.googlecode.com) PHP Framework
 * Copyright (c) 2008, Wess D. Cope <wess@wattz.net>
 * All rights reserved.								
 *													
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:				   
 *																				
 *	* Redistributions of source code must retain the above copyright notice,	
 *	this list of conditions and the following disclaimer.						
 *																				
 *	* Redistributions in binary form must reproduce the above copyright notice, 
 *	this list of conditions and the following disclaimer in the documentation	
 *	and/or other materials provided with the distribution.						
 *																				
 *	* Neither the name of the <ORGANIZATION> nor the names of its contributors may
 *	be used to endorse or promote products derived from this software without	  
 *	specific prior written permission.											
 *																				
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY	 
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES	 
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT	 
 * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,		 
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED	 
 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR	 
 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN		 
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN	 
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH	 
 * DAMAGE.																				 
 **/

ALFileLoad::lib(ALValidator);

class ALForms {

	protected $fields = array();
	protected $groups = array();
	protected $data	  = NO;
	protected $excludeFields;

	public function __construct ($data = NO, Array $excludeFields = null) {

		$data = ($data == NO) ? array() : $data;
		$this->load($data,$excludeFields);

	}

	public function __get ($name) {

		if (isset($this->fields[$name])) {

			return $this->fields[$name];

		}

		return NO;

	}

	public function __set ($name, $value) {
		
		$this->fields[$name] = $value;

	}

	public function addGroup ($func, Array $params) {

		$this->groups[] = array('func'	 => $func,
								'params' => $params);

	}

	public function isValid () {

		static $fieldErrors;
		
		if (!$fieldErrors) {

			$fieldErrors = ALFormatParser::yaml(ROOT_DIR . 'system/conf/fielderrors.conf');

		}
		
		$error = NO;

		foreach ($this->groups as $group) {

			$func	= $group[0];
			$params = $group[1];
			$values = array();

			foreach ($params as $param) {

				$values[] = isset($this->data[$param]) ? $this->data[$param] : '';

			}

			if (call_user_func_array("ALGroup::$func", $values)) {

				foreach ($params as $param) {

					$this->fields[$param]['required'] = YES;

				}

			}

		}

		foreach ($this->fields as $field => $data) {
			
			if($this->excludeFields != null)
			{
				foreach($excludeFields as $exField)
				{	
					$fieldValues[$exField] = '';
					$this->fields[$exField]['required'] = false;
				}
			}
			

			$value = isset($this->data[$field]) ? $this->data[$field] : '';
			if ($data['type'] == 'select') {

				$this->fields[$field]['field'] = str_replace("value=\"{$value}\"", "value=\"{$value}\" selected=\"selected\"", $this->fields[$field]['field']);

			} else {

				if (isset($data['default'])) {

					$this->fields[$field]['field'] = str_replace('value="' . $data['default'] . '"', 'value="' . htmlspecialchars($value) . '"', $this->fields[$field]['field']);

				} else {

					$this->fields[$field]['field'] = str_replace('value=""', 'value="' . htmlspecialchars($value) . '"', $this->fields[$field]['field']);

				}

			}

			if ($data['required'] && $value == '') {

				$error = YES;

				$this->fields[$field]['errors'][] = 'This field is required';
			
			} else {

				$validators = explode(',', $data['validator']);

				foreach ($validators as $validator) {

					$validator = trim($validator);

					if (!empty($validator) && !call_user_func(array('ALValidator', $validator), $data, $value)) {

						$error = YES;

						$this->fields[$field]['errors'][] = sprintf($fieldErrors[$validator], '%s', $data['name']);

					}

				}

			}

		}
		return !$error;

	}
	
	private function prePop(Array $fieldValues, Array $excludeFields = null)
	{

		foreach ($this->fields as $field => $data) {

			$value = isset($fieldValues[$field]) ? $fieldValues[$field] : '';

			if ($data['type'] == 'select') {

				if(isset($fieldValues[$field])) {

					$this->fields[$field]['initial'] = $fieldValues[$field];
					$this->fields[$field] = SelectField($this->fields[$field]);

				}

			} else {

				if (isset($data['default'])) {

					$this->fields[$field]['field'] = str_replace('value="' . $data['default'] . '"', 'value="' . htmlspecialchars($value) . '"', $this->fields[$field]['field']);

				} else {

					$this->fields[$field]['field'] = str_replace('value=""', 'value="' . $value . '"', $this->fields[$field]['field']);

				}

			}

		}

		// Empty all excluded fields values and make them not required
		if($excludeFields != null) {

			foreach($excludeFields as $exField) {

				$fieldValues[$exField]['value'] = '';
				$this->fields[$exField]['required'] = false;

			}

		}

	}
	
	/**
	 * Return array of form fields.  Optionally set the pre-populated data and excluded fields
	 *
	 * @param	array	An array of field values in a 'fieldname' => 'value' format.
	 * @param	array	array of fields to not pre poluate in array('fieldname-1','fieldname-2')
	 * 					format.
	 *
	 * @return	array	An array of form field objects.
	 **/
	public function load (Array $data = null, Array $excludeFields = null) {

		if($data != null)
			$this->prePop($data, $excludeFields);

		return $this->fields;

	}
	
}
